//
//  RestModel.swift
//  sui04mac
//
//  Created by 杨剑 on 2023/11/23.
//

import Foundation
import Alamofire
import HandyJSON

//enum RequestMethod {
//    case GET
//    case POST
//    case PUT
//    case PATCH
//    case DELETE
//    case COPY
//    case HEAD
//    case OPTIONS
//    case LINK
//    case UNLINK
//    case PURGE
//}

enum RequestDataType :Int, HandyJSONEnum {
    
    case multipart__form_data  = 0 //传输文件使用
    case application__x_www_form_urlencoded = 1    //在环信中用户属性使用
    case application__json = 2 //常规用法
    case application__xml = 3   //无用
    case application__javascript = 4   //无用
    case text__plain = 5    //无用
    case text__html = 6    //无用
}

//enum ParameterType {
//    case string
//    case array
//    case dictionary
//}


enum RestSerTag: HandyJSONEnum {
    static func _transform(from object: Any) -> RestSerTag? {
        let f = object as! String
        if f == "app"{
            return .app
        }
        if f == "user"{
            return .user
        }
        if f == "userinfo"{
            return .userinfo
        }
        if f == "chat"{
            return .chat
        }
        if f == "contacts"{
            return .contacts
        }
        if f == "group"{
            return .group
        }
        if f == "room"{
            return .room
        }
        if f == "message"{
            return .message
        }
        if f == "push"{
            return .push
        }
        return .app
    }
    
    func _plainValue() -> Any? {
        if self == .app { return "app" }
        if self == .user { return "user" }
        if self == .chat { return "chat" }
        if self == .contacts { return "contacts" }
        if self == .group { return "group" }
        if self == .room { return "room" }
        if self == .message { return "message" }
        if self == .push { return "push" }
        return "app"
    }
    
    func fetchName() -> String {
        if self == .app { return "app" }
        if self == .user { return "user" }
        if self == .userinfo { return "userinfo" }
        if self == .chat { return "chat" }
        if self == .contacts { return "contacts" }
        if self == .group { return "group" }
        if self == .room { return "room" }
        if self == .message { return "message" }
        if self == .push { return "push" }
        return "undefined"
    }
    
    static func fetchAllCase() -> [RestSerTag] {
        return [
            .user,
            .userinfo,
            .chat,
            .contacts,
            .group,
            .room,
            .message,
            .app,
            .push,
        ]
    }
    
    case app
    case user
    case userinfo
    case chat
    case contacts
    case group
    case room
    case message
    case push
}

//enum RestVerifyType{
//    case none
//    case
//}

struct ParamDescription : Identifiable {
    var id: Int
    var name = "msg:text"
    var must = false
    var content = "这是一个参数这是一个参数这是一个参数这是一个参数这是一个参数这是一个参数这是一个参数这是一个参数这是一个参数这是一个参数这是一个参数这是一个参数这是一个参数"
    
}



struct RestModel : Identifiable,Hashable,HandyJSON{
    init() {
        self.init(id: generateID())
    }
    
    init(id: Int , T: Int = 1, name: String = "获取用户信息", urlTemplate: RestURLTemplate = RestURLTemplate(), tags: [RestSerTag] = [], paramExample: [String : Any] = [:], paramDescriptions: [ParamDescription] = []) {
        self.id = id
        self.T = T
        self.name = name
        self.urlTemplate = urlTemplate
        self.tags = tags
        self.paramExample = paramExample
        self.paramDescriptions = paramDescriptions
    }
    static func == (lhs: RestModel, rhs: RestModel) -> Bool {
        return lhs.id == rhs.id
    }
    func hash(into hasher: inout Hasher) {
        hasher.combine(id)
    }
    var id : Int
    var T : Int
    var name = "获取用户信息"
    var urlTemplate = RestURLTemplate()
    var tags : [RestSerTag] = []
//    var paramType = ParameterType.string
//    var paramExample : Any?
    var needParam = true
    var paramExample : [String : Any] = [:]
    var paramDescriptions : [ParamDescription] = [
        ParamDescription(id: 0),
        ParamDescription(id: 1),
        ParamDescription(id: 2),
        ParamDescription(id: 3),
    ]
}

struct RestURLTemplate : HandyJSON  {
    var method = HTTPMethod.get
    var original_urlString = "{host}/{org}/{app}/users/{username}"
    var needAuthorizationVerify = true
    var contentType = RequestDataType.application__json
    
    var arguments : [String] {
        //这里是过滤方式,这边只用了分隔符进行过滤
        return original_urlString.components(separatedBy: "/").filter { arg in
            //正则,{开头,}结束,中间不能包含"{/}"三个字符
//            let regex = try! NSRegularExpression(pattern: "^\\{[^/\\{\\}]*\\}$", options: [])
//            let string = arg
//            let nsString = arg as NSString
//            return regex.matches(in: arg, options: [], range: NSRange(location: 0, length: nsString.length)).count > 0
            arg.first == "{" && arg.last == "}" && arg != "{host}" && arg != "{org}" && arg != "{app}"
        }
    }
}




struct SectionModel: Hashable,Identifiable {
    
//    init(id:Int = 0, sectionIndex: Int = 0, title: String = "用户", show: Bool = false) {
//        self.sectionIndex = sectionIndex
//        self.title = title
//        self.show = show
//    }
//
    var items : [RestModel]
//    [
//        
//        RestModel(id: 0,urlTemplate: RestURLTemplate(original_urlString: "{host}/{org}/{app}/users/{username}")),
//        RestModel(id: 1,name: "注册用户",urlTemplate: RestURLTemplate(method: .post,original_urlString: "{host}/{org}/{app}/users"),paramExample: ["username": "test_username123","password": "test_password"]),
//        RestModel(id: 2),
//        RestModel(id: 3),
//        RestModel(id: 4),
//        RestModel(id: 5),
////        RowItem(id: 0,title: "123"),
////        RowItem(id: 1,title: "123"),
////        RowItem(id: 2,title: "123"),
////        RowItem(id: 3,title: "123"),
////        RowItem(id: 4,title: "123"),
//    ]
    var id: Int
    var tag = RestSerTag.app
    var sectionIndex = 0
    var title = "用户"
    var show = false

//    static func == (lhs: SectionModel, rhs: SectionModel) -> Bool {
//        return lhs.id < rhs.id
//    }
//    func hash(into hasher: inout Hasher) {
//        hasher.combine(id)
////        hasher.combine(show)
//    }
}



struct RestIndex : Equatable {
    var sectionIndex = 0
    var restIndex = 0
}

@Observable//可以监视,同时会同步到视图上.仅写满足Observable协议是无法填入到视图上的
class RestModelData /*: Observable*/{
    
//    var currentRest:RestModel = (sectionModels.first?.items.first)!
    var currentRestIndex  = RestIndex()
    
//    func fetchCurrentRest() -> RestModel {
//        if sectionModels.count > currentRestIndex.sectionIndex {
//            let section = sectionModels[currentRestIndex.sectionIndex]
//            if section.items.count > currentRestIndex.restIndex {
//                return section.items[currentRestIndex.restIndex]
//            }
//        }
//        currentRestIndex.sectionIndex = 0
//        currentRestIndex.restIndex = 0
//        return (sectionModels.first?.items.first)!
//    }

    var currentRest : RestModel {
        if sectionModels.count > currentRestIndex.sectionIndex {
            let section = sectionModels[currentRestIndex.sectionIndex]
            if section.items.count > currentRestIndex.restIndex {
                return section.items[currentRestIndex.restIndex]
            }
        }
        currentRestIndex.sectionIndex = 0
        currentRestIndex.restIndex = 0
        
        return (sectionModels.first?.items.first)!
    }
    
    var sectionModels : [SectionModel] = load("RestData.json")
    
//    var sectionModels : [SectionModel] = [
//        SectionModel(id:0,sectionIndex: 0,title: "用户",show: true),
//        SectionModel(id:1,sectionIndex: 1,title: "用户关系",show: false),
//        SectionModel(id:2,sectionIndex: 2,title: "群组",show: false),
//        SectionModel(id:3,sectionIndex: 3,title: "聊天室",show: false),
//        SectionModel(id:4,sectionIndex: 4,title: "推送",show: false),
//    ]
}


func load(_ filename: String) -> [SectionModel] {
    let data: Data
    guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
        else {
            fatalError("Couldn't find \(filename) in main bundle.")
    }

    do {
        data = try Data(contentsOf: file)
    } catch {
        fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
    }

    let result = String(data: data, encoding: .utf8) ?? ""
    if result.isEmpty {
        return []
    }
    
    
    
    do {
        let jsonObject = try JSONSerialization.jsonObject(with: result.replacingOccurrences(of: "\r\n", with: "").data(using: .utf8)!, options: [.allowFragments]) as? [[String : Any]]?
        print(jsonObject as Any)
        var restModels = [RestModel]()
        guard let restMaps = (jsonObject ?? []) as [[String : Any]]? else{
            return []
        }
        for restMap in restMaps {
            var rest = RestModel()
            rest.id = restMap["id"] as! Int
            rest.T = restMap["T"] as! Int
            rest.name = restMap["name"] as! String
            rest.tags = [RestSerTag]()
            
            if let paramExample = restMap["paramExample"] as? [String : Any] {
                if paramExample.isEmpty {
                    rest.needParam = false
                }else {
                    rest.needParam = true
                    rest.paramExample = paramExample
                }
            }
            
//            rest.paramExample = restMap["paramExample"] as? [String : Any]
            
            if let tags = restMap["tags"] as! [String]? {
                for tag in tags {
                    if tag == "app"{
                        rest.tags.append(.app)
                    }
                    if tag == "user"{
                        rest.tags.append(.user)
                    }
                    if tag == "userinfo"{
                        rest.tags.append(.userinfo)
                    }
                    if tag == "chat"{
                        rest.tags.append(.chat)
                    }
                    if tag == "contacts"{
                        rest.tags.append(.contacts)
                    }
                    if tag == "group"{
                        rest.tags.append(.group)
                    }
                    if tag == "room"{
                        rest.tags.append(.room)
                    }
                    if tag == "message"{
                        rest.tags.append(.message)
                    }
                    if tag == "push"{
                        rest.tags.append(.push)
                    }
                }
            }
            rest.urlTemplate = RestURLTemplate()
            if let urlTemplateMap = restMap["urlTemplate"] as! [String : Any]? {
                rest.urlTemplate.method = HTTPMethod(rawValue: urlTemplateMap["method"] as! String)
                rest.urlTemplate.original_urlString = urlTemplateMap["original_urlString"] as! String
                rest.urlTemplate.needAuthorizationVerify = urlTemplateMap["needAuthorizationVerify"] as! Bool
                rest.urlTemplate.contentType = RequestDataType(rawValue: urlTemplateMap["contentType"] as! Int) ?? RequestDataType.application__json
            }
            restModels.append(rest)
        }
        var sectionModels = [SectionModel]()
        var index = 0
        for tag in RestSerTag.fetchAllCase() {
            sectionModels.append(SectionModel(items: [RestModel](),id: index, tag:tag,sectionIndex: index,title: tag.fetchName(),show: index == 0))
            index += 1;
        }
        
        for restIndex in 0 ..< restModels.count {
            for i in 0 ..< sectionModels.count {
                if restModels[restIndex].tags.contains(sectionModels[i].tag) {
                    sectionModels[i].items.append(restModels[restIndex])
                }
            }
        }
        
//        restModels.forEach { rest in
////            if let i = sectionModels.firstIndex(where:) {
////                sectionModels[i].items.append(rest)
////            }
//
//            for i in 0 ..< sectionModels.count {
//                if rest.tags.contains(sectionModels[i].tag) {
//                    sectionModels[i].items.append(rest)
//                }
//            }
//            
////            rest.tags.forEach { tag in
////                if let i = sectionModels.firstIndex(where: { $0.tag == tag }) {
////                    sectionModels[i].items.append(rest)
////                }
////            }
//        }
        return sectionModels
        
    } catch {
        fatalError("Couldn't parse \(filename)\n\(error)")
    }

//    if let jsonObject {
//        body = jsonObject
//    }
//
//    let rests = JSONDeserializer<Dictionary<String, Any>>.deserializeFrom(json: result.replacingOccurrences(of: "\r\n", with: ""))
//    result.jsonToModel

//        do {
//            let decoder = JSONDecoder()
//            return try decoder.decode(T.self, from: data)
//        } catch {
//            fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
//        }
//
    
    
//    return []
//    do {
//        let decoder = JSONDecoder()
//        return try decoder.decode(T.self, from: data)
//    } catch {
//        fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
//    }


}
//"\r\n[\r\n    {\r\n        \"id\" = 1001,\r\n        \"name\" = \"获取用户信息\",\r\n        \"urlTemplate\":{\r\n            \"method\" : \"get\"\r\n            \"original_urlString\" : \"{host}/{org}/{app}/users/{username}\"\r\n            \"contentType\" : \"2\"\r\n        },\r\n        \"tags\" : [\r\n            \"user\",\r\n            \"push\"\r\n        ],\r\n        \"paramExample\":{}\r\n    },\r\n    {\r\n        \"id\" = 1002,\r\n        \"name\" = \"注册用户\",\r\n        \"urlTemplate\":{\r\n            \"method\" : \"post\"\r\n            \"original_urlString\" : \"{host}/{org}/{app}/users/{username}\"\r\n            \"contentType\" : \"2\"\r\n        },\r\n        \"tags\" : [\r\n            \"user\",\r\n        ],\r\n        \"paramExample\":{\"username\": \"testuser\" , \"password\": \"testpassword\",\"nickname\": \"<推送显示这个昵称>\"}\r\n    },\r\n    {\r\n        \"id\" = 1003,\r\n        \"name\" = \"批量注册用户\",\r\n        \"urlTemplate\":{\r\n            \"method\" : \"post\"\r\n            \"original_urlString\" : \"{host}/{org}/{app}/users/{username}\"\r\n            \"contentType\" : \"2\"\r\n        },\r\n      "...
